home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1996 October / MACPOWER-1996-10.ISO.7z / MACPOWER-1996-10.ISO / AMUG / Internet_31 / NetCacheResolver 0.9d6 / NetCacheResolver 0.9d6 ト / library / NCR_Message.c < prev    next >
Text File  |  1996-05-12  |  12KB  |  582 lines

  1. // #define DEBUG_ANSI 1
  2. // Basic Toolkit, 1994 (C) Mizutori Tetsuya
  3. // - MessageUtils.c, 1994/10/6, 1995/8/6
  4.  
  5. #include <stdio.h>
  6. #include <stdarg.h>
  7.  
  8. #include "NCR_Message.h"
  9.  
  10.  
  11. #ifdef COMMENT
  12. [Flag character]
  13. -    Left-justify
  14. +    print with a plus sign '+'
  15. ' '    Prefix a number with a space
  16. #    %#s for Pascal-style string
  17. 0    pad the field with leading zeros
  18.  
  19. [Field size]
  20. *    Use the next argument (integer) as the field size
  21.  
  22. [Argument size]
  23. h    for short
  24. l,L    for long
  25.  
  26. [Conversion characters]
  27. c    a single character
  28. s    a string, with # for Str255
  29. e,E,f    a signed decimal floating/fixed - point number
  30. g,G    
  31. d,i,u    a signed/unsigned decimal integer
  32. o    an unsigned octal integer
  33. x,X    an unsigned hexadecimal integer
  34. n,p    an eight-digit hexadecimal value
  35. %    a percent sign
  36. S,P    Macintosh Pascal-style string for Str255
  37. t,T    Macintosh Toolbox types, eg. OSType, four-byte constant
  38. #endif /*COMMENT */
  39.  
  40.  
  41. // define constants
  42. #define    EOS            '¥0'
  43.  
  44. enum {
  45.     kflag_none        =    0,    /* no */
  46.     kflag_short    =    1,    /* h */
  47.     kflag_long        =    2,    /* l */
  48.     kflag_ldouble    =    3,    /* L */
  49.     kflag_pound    =    4,    /* # */
  50.     kflag_aster    =    5,    /* * */
  51.     kflag_left        =    6,    /* - */
  52.     kflag_plus        =    7,    /* + */
  53.     kflag_space    =    8,    /* ' ' */
  54.     kflag_zeros    =    9,    /* %0 */
  55.     kflag_dot        =    10    /* . */
  56. };
  57.  
  58. #define    kHexShortFS    4
  59. #define    kHexLongFS    8
  60. #define    kOctShortFS    6
  61. #define    kOctLongFS        11
  62.  
  63.  
  64. // prptotype
  65. /***** static functions *****/
  66. static void vsMessage ( char *text, const char *format, va_list ap );
  67. static Boolean TestType ( short c );
  68. static char * GetDirective ( char *p, long *flag, long *fieldSize );
  69.  
  70. static void WriteChars ( char *cstr );
  71. static void WriteChar( short c );
  72.  
  73. static StringPtr NumToHex ( unsigned long n, StringPtr format, short digits );
  74. static StringPtr NumToOct ( unsigned long n, StringPtr format, short digits );
  75.  
  76.  
  77. /***** message test *****/
  78. #ifdef TEST
  79. void MessageTest ( void )
  80. {
  81.     short        i;
  82.     char        c = 'm';
  83.     short        n = 33;
  84.     long        x = 3333333;
  85.     double    f = 333.333;
  86.     OSType    t = 'odoc';
  87.     char        s[8] = "yes!";
  88.     char        s2[16] = "01234567890123";
  89.     Str31    p = "¥ppascal!";
  90.  
  91.     
  92. //    for (i=1;i<=100;++i) {
  93. //        Message( "This is %3d lines. Mizutori Tetsuya + Mizutori Misuzu¥n", i );
  94. //    }
  95.  
  96.     Message("¥n");
  97.     Message("test '%010d'='%-10d' +'%010s'='%-010s'¥n",n,n,s,s);
  98.     Message("test '%010s'='%s' +'%010s'='%s'¥n",s,s,s2,s2);
  99.     Message("OSType('%4s') = ('%-10t')¥n",&t, t);
  100.     Message("string('%10s'), ('%-10S')¥n",s,p);
  101.     
  102.     Message("short=%d, hex=0x%*lx¥ndouble=%lf, pointer=%p¥n" ¥
  103.             "cstr=%s, char='%c'¥n" ¥
  104.             "pstr=%#s¥n",
  105.             n,7,x,f,&s,s,c,p);
  106. }
  107. #endif /* TEST */
  108.  
  109. /***** set up *****/
  110. #define    MAXLENGTH    2048
  111. void Message ( const char *format, ... )
  112. {
  113.     va_list    ap;
  114.     char        text[MAXLENGTH];
  115.    
  116.     va_start( ap, format );
  117.     vsMessage( text, format, ap );
  118.     va_end( ap );
  119.  
  120.     WriteChars( text );
  121. }
  122.  
  123. void sMessage ( char *text, const char *format, ... )
  124. {
  125.     va_list    ap;
  126.  
  127.     va_start( ap, format );
  128.     vsMessage( text, format, ap );
  129.     va_end( ap );
  130. }
  131.  
  132.  
  133. /***** Message Window *****/
  134. #define    kBaseResID        128
  135. #define    kMoveToFront        (WindowPtr) -1L
  136.  
  137. /***** Constants & Globals *****/
  138. short        kLeftMargin        = 4;
  139. short        kRowStart            = 285;
  140. short        kFontSize            = 9;
  141. short        kRowHeight        = 11;    /* kFontSize+2 */
  142. short        kHorizontalOffset    = 0;
  143.  
  144. WindowPtr    gMsgWindow        = nil;
  145.  
  146. /***** create MessageBoard window *****/
  147. void NewMessage ( void )
  148. {
  149.     WindowPtr    window;
  150.     Rect        windRect;
  151.     GrafPtr    oldPort;
  152.     
  153.     window = GetNewWindow( kBaseResID, nil, kMoveToFront );
  154.     if ( window == nil ) {
  155.         SysBeep(10);
  156.         ExitToShell(); }
  157.     
  158.     GetPort( &oldPort );
  159.     SetPort( window );
  160.     
  161.     TextSize( kFontSize );
  162.     
  163.     ShowWindow( window );
  164.     
  165.     gMsgWindow = window;
  166.     
  167.     SetPort( oldPort );
  168. }
  169.  
  170. /***** WriteTextln *****/
  171. static void WriteChars ( char *text )
  172. {
  173.     long        i = 0, k = 0;
  174.     char        c;
  175.     Str255    str = "¥p";
  176.  
  177. //    while ( (c=text[i++]) != EOS ) WriteChar( (unsigned char) c );
  178.  
  179.     while ( (c=text[i++]) != EOS ) {
  180.         if (c == '¥n' || c == '¥r' ) {
  181.             str[0] = k;
  182.             WriteTextln(str);
  183.             k = 0;
  184.         } else if ( k > 250 ) {
  185.             str[0] = k;
  186.             WriteText(str);
  187.             k = 0;
  188.         } else {
  189.             str[++k] = c;
  190.         }
  191.     }
  192.     
  193.     if ( k > 0 ) {
  194.         str[0] = k;
  195.         WriteText( str );
  196.     }
  197. }
  198.  
  199. static void WriteChar( short c )
  200. {
  201.     GrafPtr    oldPort;
  202.  
  203.     if ( gMsgWindow == nil ) return;
  204.     
  205.     GetPort( &oldPort );
  206.     SetPort( gMsgWindow );
  207.     
  208.     if ( c == '¥n' || c == '¥r' ) WriteTextln("¥p");
  209.     else DrawChar( c );
  210.  
  211.     SetPort( oldPort );
  212. }
  213.  
  214. void WriteTextln ( StringPtr text )
  215. {
  216.     RgnHandle    tempRgn;
  217.     WindowPtr    window;
  218.     GrafPtr    oldPort;
  219.     
  220.     if ( gMsgWindow == nil ) return;
  221.     
  222.     GetPort( &oldPort );
  223.     SetPort( gMsgWindow );
  224.     
  225.     DrawString( text );
  226.  
  227.     window = FrontWindow();
  228.     tempRgn = NewRgn();
  229.     ScrollRect( &window->portRect, kHorizontalOffset, -kRowHeight, tempRgn );
  230.     DisposeRgn( tempRgn );
  231.     
  232.     MoveTo( kLeftMargin, (window->portRect).bottom - 2 );
  233.     
  234.     SetPort( oldPort );
  235. }
  236.  
  237. void WriteText ( StringPtr text )
  238. {
  239.     GrafPtr    oldPort;
  240.  
  241.     if ( gMsgWindow == nil ) return;
  242.  
  243.     GetPort( &oldPort );
  244.     SetPort( gMsgWindow );
  245.     
  246.     DrawString( text );
  247.     
  248.     SetPort( oldPort );
  249. }
  250.  
  251. void WriteTextNumb ( long value )
  252. {
  253.     Str31    text;
  254.     GrafPtr    oldPort;
  255.  
  256.     if ( gMsgWindow == nil ) return;
  257.  
  258.     GetPort( &oldPort );
  259.     SetPort( gMsgWindow );
  260.     
  261.     NumToString( value, text );
  262.     DrawString( text );
  263.     
  264.     SetPort( oldPort );
  265. }
  266.  
  267. void WriteTextType ( OSType type )
  268. {
  269.     Str32    text = "¥p****";
  270.     GrafPtr    oldPort;
  271.     
  272.     if ( gMsgWindow == nil ) return;
  273.     
  274.     GetPort( &oldPort );
  275.     SetPort( gMsgWindow );
  276.     
  277.     BlockMove( &type, &text[1], 4);
  278.     DrawString( text );
  279.     
  280.     SetPort( oldPort );
  281. }
  282.  
  283. void WriteTextPeek ( Ptr dataPtr, Size length )
  284. {
  285.     long            i;
  286. //    Size            hSize;
  287.     unsigned char    *p, c;
  288.     Str31        text = "¥p*";
  289.     Str31        text2 = "¥p¥¥**";
  290.     unsigned char    hex[17] = "0123456789abcdef";
  291.     GrafPtr        oldPort;
  292.     
  293.     if ( gMsgWindow == nil ) return;
  294.  
  295.     GetPort( &oldPort );
  296.     SetPort( gMsgWindow );
  297.     
  298.     p = (unsigned char *) dataPtr;
  299. //    hSize = GetPtrSize( dataPtr );
  300.     
  301.     if ( length > 8 ) WriteTextln("¥p");
  302.     
  303.     for ( i=0; i<length; ++i ) {
  304.         if ( (i > 0) && ( (i % 16) == 0 ) ) WriteTextln("¥p");
  305.         c = p[i];
  306.         //if ( c < ' ' || c > 0x7E ) c = '.';
  307.         if ( c < ' ' || c > 0x7E ) {
  308.             text2[2] = hex[(c>>4) & 0x0f]; text2[3]=hex[c & 0x0f];
  309.             DrawString( text2 );
  310.         } else {
  311.             text[1] = c;
  312.             DrawString( text );
  313.         }
  314.     }
  315.     
  316.     SetPort( oldPort );
  317. }
  318.  
  319. /***** static functions *****/
  320.  
  321. #define bitTst(flag,bit)    ( (Boolean) ( ((flag) & (1 << (bit))) != 0 ) )
  322. #define bitSet(flag,bit)    ( flag |= (1 << (bit)) )
  323.  
  324. #define va_arg_int( ap, flag )  ¥
  325.     ( bitTst(flag,kflag_long) ? va_arg(ap,long) : va_arg(ap,short) )
  326.  
  327. #define va_arg_uint( ap, flag )  ¥
  328.     ( bitTst(flag,kflag_long) ? va_arg(ap,unsigned long) : va_arg(ap,unsigned short) )
  329.  
  330. #define va_arg_float( ap, flag )  ¥
  331.     ( bitTst(flag,kflag_long) ? va_arg(ap,long double) : va_arg(ap,short double) )
  332.  
  333. #define FieldSize(fs,shortfs,longfs) ¥
  334.     ( (fs) > 0 ? (fs) : ( bitTst(flag,kflag_long) ? (longfs) : (shortfs) ) )
  335.  
  336.  
  337. static void vsMessage ( char *text, const char *format, va_list ap )
  338. {
  339. //    va_list        ap;
  340.     long            n;
  341.     short            i, j, k, h;
  342.     char            c, d, zeroChar;
  343.     char            *p, *q, *s;
  344.     long            value;
  345.     unsigned long    uvalue;
  346.     long double        fvalue;
  347.     long            flag;
  348.     long            digits;
  349.     Boolean        shiftLeft;
  350.     Str63        str;
  351.     
  352.  
  353. //    va_start( ap, format );
  354.  
  355.     n = 0; p = (char *) format;
  356.     while ( (c=*(p++)) != EOS /* && n<MAXLENGTH-20 */ ) {
  357.  
  358.         if ( c != '%' ) { text[n++] = c; continue; }
  359.  
  360.         digits = 0;
  361.  
  362.         q = p;
  363.         p = GetDirective ( p, &flag, &digits );
  364.  
  365.         if ( (c=*(p++)) == EOS ) { --p; break; }
  366.         
  367.         zeroChar = ( bitTst(flag,kflag_zeros) ? '0' : ' ' );
  368.         shiftLeft = bitTst( flag, kflag_left );
  369.         
  370.         if ( bitTst( flag, kflag_aster ) && TestType( (unsigned char) c ) ) {
  371.             digits = va_arg( ap, short ); }
  372.  
  373.         switch ( c ) {
  374.             case_int:
  375.             case 'i':
  376.             case 'd':
  377.                 value = va_arg_int( ap, flag );
  378.                 NumToString( value, str );
  379.                 goto case_printdigit;
  380.                 break;
  381.             case 'u':
  382.                 value = va_arg_uint( ap, flag );
  383.                 NumToString( value, str );
  384.                 goto case_printdigit;
  385.                 break;
  386.             case_hex:
  387.             case 'x':
  388.             case 'X':
  389.                 value = va_arg_uint( ap, flag );
  390.                 NumToHex( value, str, FieldSize(digits,kHexShortFS,kHexLongFS) );
  391.                 goto case_printdigit;
  392.                 break;
  393.             case_oct:
  394.             case 'o':
  395.                 value = va_arg_uint( ap, flag );
  396.                 NumToOct( value, str, FieldSize(digits,kOctShortFS,kOctLongFS) );
  397.                 goto case_printdigit;
  398.                 break;
  399.             case_float:
  400.             case 'f':
  401.             case 'e':
  402.             case 'E':
  403.             case 'g':
  404.             case 'G':
  405.                 fvalue = va_arg_float( ap, flag );
  406.                 value = fvalue;
  407.                 NumToString( value, str );
  408.                 goto case_printdigit;
  409.                 break;
  410.             case_pointer:
  411.             case 'p':
  412.             case 'n':
  413.                 value = (unsigned long) va_arg( ap, void * );
  414.                 NumToHex( value, str, kHexLongFS );
  415.                 goto case_printdigit;
  416.                 break;
  417.             case 't':
  418.             case 'T':
  419.                 value = (unsigned long) va_arg( ap, void * );
  420.                 str[0] = sizeof(OSType);
  421.                 BlockMove( &value, &str[1], str[0] );
  422.                 goto case_printdigit;
  423.                 break;
  424.             case_printdigit:
  425.                 k = str[0];
  426.                 s = (char *) &str[1];
  427.                 goto case_printstr;
  428.                 break;
  429.             case 's':
  430.                 s = va_arg( ap, char * );
  431.                 if ( bitTst( flag, kflag_pound ) ) {
  432.                     if ( digits == 0 )
  433.                         goto case_pstr0;
  434.                     else
  435.                         goto case_pstr1;
  436.                 } else {
  437.                     if ( digits == 0 )
  438.                         goto case_cstr0;
  439.                     else
  440.                         goto case_cstr1;
  441.                 }
  442.                 break;
  443.             case 'S':
  444.             case 'P':
  445.                 s = va_arg( ap, char * );
  446.                 goto case_pstr0;
  447.                 break;
  448.             case_cstr0:
  449.                 k = 0; while ( s[k] != EOS ) ++k;
  450.                 goto case_printstr;
  451.                 break;
  452.             case_cstr1:
  453.                 k = 0; while ( s[k] != EOS && k<digits ) ++k;
  454.                 goto case_printstr;
  455.                 break;
  456.             case_pstr0:
  457.             case_pstr1:
  458.                 k = * (unsigned char *) s;
  459.                 ++s;
  460.                 goto case_printstr;
  461.                 break;
  462.             case_printstr:
  463.                 // digits = field width
  464.                 // k = string length
  465.                 // *s = start of string
  466.                 h = digits - k; if ( h < 0 ) h = 0;
  467.                 if ( ! shiftLeft )
  468.                     while ( --h >= 0 )  text[n++] = zeroChar;
  469.                 while ( --k >= 0 ) text[n++] = *(s++);
  470.                 if ( shiftLeft )
  471.                     while ( --h >= 0 )  text[n++] = zeroChar;
  472.                 break;
  473.             case_char:
  474.             case 'c':
  475.                 value = va_arg( ap, unsigned short );    /* not 'char' */
  476.                 text[n++] = value;
  477.                 break;
  478.             case '%':
  479.                 text[n++] = c;
  480.                 break;
  481.             case_none:
  482.             default:
  483.                 p = q;
  484.                 text[n++] = '%';
  485.                 break;
  486.         }
  487.     }
  488.     text[n++] = EOS;
  489.  
  490. //    va_end( ap );
  491.  
  492.     for (i=1;i<=n;++i) if ( text[i] == '¥n' ) text[i] = '¥r';
  493. }
  494.  
  495.  
  496. static Boolean TestType ( short c )
  497. {
  498.     register short    n = 0;
  499.     register short    d;
  500.     char             types[] = "dioxXucsfeEgGpntTSP";
  501.     
  502.     while ( (d=types[n++]) != EOS )
  503.         if ( c == d )  return true;
  504.     
  505.     return  false;
  506. }
  507.  
  508.  
  509. static char * GetDirective ( char *p, long *flag, long *fieldSize )
  510. {
  511.     char        c;
  512.     long        fflag = 0;
  513.     long        n = 0;
  514.     Boolean    done = false;
  515.     char        text[32] = "";
  516.     
  517.     while ( (c=*p) != EOS && ! done ) { ++p;
  518.         if ( '0' <= c && c <= '9' )  {
  519.             if ( n < 31  && ! bitTst(fflag,kflag_dot) ) {
  520.                 text[n++] = c; text[n] = EOS; }
  521.             continue; }
  522.         switch ( c ) {
  523.             case '+':    bitSet( fflag, kflag_plus ); break;
  524.             case '-':    bitSet( fflag, kflag_left ); break;
  525.             case ' ':    bitSet( fflag, kflag_space ); break;
  526.             case '.':    bitSet( fflag, kflag_dot ); break;
  527.             case 'h':    bitSet( fflag, kflag_short ); break;
  528.             case 'l':    bitSet( fflag, kflag_long ); break;
  529.             case 'L':    bitSet( fflag, kflag_long ); break;
  530.             case '*':    bitSet( fflag, kflag_aster ); break;
  531.             case '#':    bitSet( fflag, kflag_pound ); break;
  532.             default:    --p; done = true; break;
  533.         }
  534.     }
  535.  
  536.     if ( n > 0 && text[0] == '0' )  bitSet( fflag, kflag_zeros );
  537.     
  538.     c2pstr( text );
  539.     StringToNum( (StringPtr) text, fieldSize );
  540.  
  541.     *flag = fflag;
  542.  
  543.     return  p;
  544. }
  545.  
  546.  
  547. /***** hex & oct number conversion *****/
  548. static char    *conv = "0123456789abcdef";
  549.  
  550. static StringPtr NumToHex ( unsigned long n, StringPtr format, short digits )
  551. {
  552. //    static StringPtr    format = "¥p00000000";
  553.     unsigned long        i;
  554.  
  555.     if ( digits > 8 || digits < 0 )  digits = 8;
  556.     
  557.     format[0] = digits;        /* adjust length byte of output string */
  558.  
  559.     for ( i=0; i<digits; ( n>>=4, ++i) )
  560.         format[ digits-i ] = conv[ n & 0x0f ];
  561.  
  562.     return format;
  563. }
  564.  
  565. static StringPtr NumToOct ( unsigned long n, StringPtr format, short digits )
  566. {
  567. //    static StringPtr    format = "¥p000000000000";
  568.     unsigned long        i;
  569.  
  570.     if ( digits > 12 || digits < 0 )  digits = 12;
  571.     
  572.     format[0] = digits;        /* adjust length byte of output string */
  573.  
  574.     for ( i=0; i<digits; ( n>>=3, ++i) )
  575.         format[ digits-i ] = conv[ n & 0x07 ];
  576.  
  577.     return format;
  578. }
  579.  
  580.  
  581. // end of program
  582.